/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Basketball;

import VISIE.characters.BasketballAgent;
import VISIE.characters.BasketballCharacter;
import VISIE.characters.Character;
import VISIE.mathfunctions.CollisionMath;
import VISIE.mathfunctions.Conversions;
import VISIE.scenemanager.Court;
import VISIE.scenemanager.SceneCharacterManager;
import com.jme3.animation.LoopMode;
import com.jme3.collision.CollisionResults;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import java.util.ArrayList;

/**
 *
 * @author Divesh
 */
public class PossessionDecision {
    
    BasketballAgent parentCharacter;
    float timeSinceReceivedBall;
    long posStartTime;
    int timeAtTargetPosition;
    float decisionTimeLimit = 20;
    
    public PossessionDecision(BasketballAgent ba){
        parentCharacter = ba;
    }
    
    public void makePossessionDecision(){
        
        timeSinceReceivedBall = Conversions.nanoToSecond(System.nanoTime() - posStartTime);
        
        if(timeSinceReceivedBall > decisionTimeLimit){ //time limit
            if(this.canShoot(25f, 5f)){
                parentCharacter.abo.turnBodyToTarget(Court.getGoalPosition());
                parentCharacter.setBehaviorState(2); //DESPERATE SHOOT
            }
            else{
                parentCharacter.setBehaviorState(4); //DESPERATE PASS
            }
        }
        else if(this.canShoot(25f, 10f)){//shoot
            parentCharacter.abo.turnBodyToTarget(Court.getGoalPosition());
            parentCharacter.setBehaviorState(2);
            System.out.println("SHOOT");
        }
        else if(!this.passCandidates().isEmpty() && timeSinceReceivedBall > 3){ //pass
            //ensure pass isnt returned straight away`
            parentCharacter.abo.turnBodyToTarget(this.passCandidates().get(0).getPosition());
            System.out.println("PASS");
            parentCharacter.setBehaviorState(101);
        }
        else{ //run
            //check if can run towards hoop
            if(this.straightToCentre()){
                parentCharacter.planner.setTargetPosition(Court.getMidCourtLocation());
            }
            else{
                parentCharacter.planner.setTargetPosition(parentCharacter.getPosition());
            }
            //player is in area of target
            
            if(parentCharacter.planner.isTargetReached(2f)){  
                ArrayList<ArrayList<String>> areas = AgentPlanning.getPlayerAreas(parentCharacter, parentCharacter);
                this.calculateBestPosition(parentCharacter, Court.getPlayerArea(parentCharacter), areas.get(0), areas.get(1));
            }
            else{//player is traveling to target position
            
            }
        } 
  //      timeSinceReceivedBall++;
        
    }
    
    private boolean canShoot(float shootRange, float opponentRange){
        float distToHoop = parentCharacter.get2DPosition().distance(Court.getHoopLocation().setY(0));
        if(distToHoop < shootRange && distToHoop > 7.5f){
            ArrayList<BasketballCharacter> opponents = parentCharacter.getOpponents();

            for(int i = 0; i < opponents.size(); i++){
                if(((opponents.get(i).get2DPosition().distance(parentCharacter.get2DPosition()) < opponentRange)
                     && AgentPlanning.isBetweenGoal(parentCharacter, opponents.get(i)))
                     || (parentCharacter.get2DPosition().distance(opponents.get(i).get2DPosition()) < 10f)
                        && parentCharacter.perception.canSeeCharacter(opponents.get(i))){
                    return false;
                }
            }
            return true;
        }
        return false;    
    
    }
    
    private ArrayList<BasketballCharacter> passCandidates(){
        
        ArrayList<BasketballCharacter> teammates = parentCharacter.getTeamMates();
        ArrayList<BasketballCharacter> opponents = parentCharacter.getOpponents();
        ArrayList<BasketballCharacter> passCandidates = new ArrayList<BasketballCharacter>();
        
        for(int i = 0; i < teammates.size(); i++){
            
            float distToCharacter = parentCharacter.get2DPosition().distance(teammates.get(i).get2DPosition());
            
            if(parentCharacter.perception.canSeeCharacter(teammates.get(i))
            && distToCharacter < 25f){
                
                Vector3f a = parentCharacter.get2DPosition();
                Vector3f b = teammates.get(i).get2DPosition();
                                    
                boolean opponentsBlocking = false;
                boolean interceptChance = false;
                
                for(int j = 0; j < opponents.size(); j++){
                    
                    if(!Conversions.isNotInBetween(a, b, opponents.get(j).get2DPosition())){
                        opponentsBlocking = true;
                    }
                    
                    if(Conversions.distancePointToLine(a, b,opponents.get(j).get2DPosition()) < 2f){
                        interceptChance = true;
                    }
                } 
                
                if(!opponentsBlocking){
                    passCandidates.add(teammates.get(i));
                }
                else if(!interceptChance){
                    passCandidates.add(teammates.get(i));
                }
            }
        }
        
        return passCandidates;
    }

    
     private void calculateBestPosition(BasketballCharacter bcInPos, String possession, ArrayList<String> teammates, ArrayList<String> opponents){
        
        //finds candidate areas
        ArrayList<String> candidates = Court.getAdjacentAreas(possession);
        
        ArrayList<String> emptyRegions = new ArrayList<String>();
        
        //labels candidate areas if they contain players
        for(int i = candidates.size() - 1; i >= 0; i--){
            for(int j = 0; j < teammates.size(); j++){
                if(candidates.get(i).equals(teammates.get(j))){
                    candidates.set(i, "T: " + candidates.get(i));
                }
            }
            for(int k = 0; k < opponents.size(); k++){
                if(candidates.get(i).equals(opponents.get(k))){
                    candidates.set(i, "O: " + candidates.get(i));
                }
            }
        }  
        
        //labels empty candidate areas
        for(int i = 0; i < candidates.size(); i++){
            if(!candidates.get(i).startsWith("O") && !candidates.get(i).startsWith("T")){
                emptyRegions.add(candidates.get(i));
            }
        }
        
        //if no empty areas, find best area from other candidates
        //if player is already in an empty area, stay in that area        
        if(!emptyRegions.isEmpty()){ 
                Vector3f bestPos = this.getBestPositionInNonOccupied(this.getClosestAreaToPlayer(emptyRegions), bcInPos);         
                parentCharacter.planner.setTargetPosition(bestPos);
        }
        //candidate areas are all occupied by players - wait
        else{
            parentCharacter.planner.setTargetPosition(parentCharacter.getPosition());
            parentCharacter.abo.turnBodyToTarget(Court.getGoalPosition());
        }
    }
     
     private Vector3f getBestPositionInNonOccupied(String area, BasketballCharacter possessor){
        
        float minDistFromPossessor = 7f;
        boolean isInArea = Court.getPlayerArea(parentCharacter).equals(area);
        
        
        if(isInArea){
            return parentCharacter.get2DPosition();
        }
        else{
            Vector3f newPos = possessor.get2DPosition();
            while(!(possessor.get2DPosition().distance(newPos) > minDistFromPossessor)){
                newPos = Court.getRandomCoordinateInArea(area);
            }
            
//            for(int i = 0; i < parentCharacter.getOpponents().size(); i++){
//                if(parentCharacter.get2DPosition().distance(newPos.setY(0)) < 20f){
//                    System.out.println("sfsdfs");
//                    return parentCharacter.get2DPosition();
//                }
//            }
            return newPos;
        }
    }
     
     private String getClosestAreaToPlayer(ArrayList<String> areas){
        float minDist = 1000000;
        String region = Court.getPlayerArea(parentCharacter);

        for(int i = 0; i < areas.size(); i++){
            float dist = parentCharacter.getPosition().distance(Court.getCentreCoordinate(areas.get(i)));
            if(dist < minDist){
                region = areas.get(i);
                minDist = dist;
            }            
        }
        return region;   
    }
     
     private boolean straightToCentre(){
                 
         ArrayList<BasketballCharacter> opponents = parentCharacter.getOpponents();
         float angleToCentre = Conversions.originToTargetAngle(parentCharacter.getPosition(), Court.getMidCourtLocation());
         Ray midRay = new Ray();
         midRay.setOrigin(parentCharacter.get2DPosition().setY(1));
         midRay.setDirection(Conversions.degreesToNormalizedCoordinates(angleToCentre));
         
         return CollisionMath.rayCollisionTest(midRay.origin, midRay.direction, parentCharacter, opponents, 3, 20);
     }
     
     public void resetPossessionTime(){
         timeSinceReceivedBall = 0;
         posStartTime = System.nanoTime();
     }  
}
